#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""SilentDragDrop - 静默拖放工具

此模块提供了一个Python实现的图形界面工具，用于静默地将文件拖放到指定位置，
无需实际移动鼠标。它通过调用C++编写的DLL来实现Windows系统级的拖放操作。

主要功能：
1. 静默拖放文件到指定坐标位置
2. 支持自动检测和加载必要的依赖项
3. 提供友好的用户界面
4. 实现3秒倒计时功能以捕获目标位置坐标

使用说明：
1. 确保libSilentDragDrop.dll和必要的MinGW运行时库已正确安装
2. 添加要拖放的文件
3. 设置拖放目标位置或使用倒计时功能捕获当前鼠标位置
4. 点击"执行拖放"按钮执行静默拖放操作
"""

import sys
import time
import ctypes
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import subprocess

class DragDropSimulator:
    """静默拖放模拟器核心类

    该类负责加载和调用静默拖放DLL，提供Python接口与C++ DLL进行交互，
    实现文件的静默拖放功能。
    
    属性:
        dll_path: DLL文件路径
        dll: 已加载的DLL对象
        SilentDragDropFiles: 从DLL导出的拖放函数
    """
    def __init__(self, dll_path=None):
        """初始化拖放模拟器
        
        参数:
            dll_path: 可选，指定DLL文件路径，默认从当前目录加载
        """
        # 默认DLL路径
        if dll_path is None:
            # 尝试从当前目录加载DLL
            self.dll_path = "libSilentMouseOperation.dll"
        else:
            self.dll_path = dll_path
        
        # 初始化DLL加载状态
        self.dll = None
        self.SilentDragDropFiles = None
        self.SilentMouseClick = None
        
        # 尝试加载DLL
        self.load_dll()
    
    def check_mingw_dependencies(self):
        """检查MinGW运行时库是否存在
        
        返回:
            list: 缺少的MinGW运行时库列表，如果全部存在则返回空列表
        """
        # MinGW核心依赖库
        mingw_dlls = ["libgcc_s_seh-1.dll", "libstdc++-6.dll", "libwinpthread-1.dll"]
        
        # 检查当前目录
        missing_dlls = []
        for dll in mingw_dlls:
            if not os.path.exists(dll):
                missing_dlls.append(dll)
        
        return missing_dlls
    
    def load_dll(self):
        """加载DLL并绑定函数
        
        该函数负责从指定路径加载静默拖放DLL，并设置函数调用的参数类型和返回类型。
        支持多种加载方式和路径搜索，并提供详细的错误诊断信息。
        
        返回:
            bool: DLL加载成功返回True，否则返回False
        """
        try:
            # 尝试获取绝对路径
            abs_dll_path = os.path.abspath(self.dll_path)
            print(f"尝试加载DLL: {abs_dll_path}")
            
            # 检查文件是否存在
            if not os.path.exists(abs_dll_path):
                print(f"DLL文件不存在: {abs_dll_path}")
                # 尝试在常见位置查找DLL
                possible_paths = [
                    os.path.abspath(os.path.join("build", "libSilentMouseOperation.dll")),
                    os.path.abspath(os.path.join("build", "Desktop_Qt_6_9_3_MinGW_64_bit-Debug", "libSilentMouseOperation.dll"))
                ]
                
                for path in possible_paths:
                    if os.path.exists(path):
                        print(f"在备用路径找到DLL: {path}")
                        abs_dll_path = path
                        break
                else:
                    error_msg = f"无法找到DLL文件: {self.dll_path}\n请确保DLL文件存在于正确位置。"
                    print(error_msg)
                    raise FileNotFoundError(error_msg)
            
            # 检查MinGW依赖项
            missing_mingw_dlls = self.check_mingw_dependencies()
            if missing_mingw_dlls:
                print(f"警告: 缺少MinGW运行时库: {', '.join(missing_mingw_dlls)}")
            
            # 尝试多种加载方式
            load_methods = [
                (ctypes.CDLL, "CDLL方式"),
                (ctypes.WinDLL, "WinDLL方式")
            ]
            
            dll_loaded = False
            for load_func, method_name in load_methods:
                try:
                    print(f"尝试{method_name}加载DLL")
                    self.dll = load_func(abs_dll_path)
                    dll_loaded = True
                    break
                except Exception as inner_e:
                    print(f"{method_name}加载失败: {str(inner_e)}")
                    continue
            
            if not dll_loaded:
                raise Exception("所有DLL加载方式均失败")
            
            # 定义函数原型
            # BOOL SilentDragDropFiles(PCWSTR* ppszFileList, UINT cFiles, INT x, INT y)
            self.SilentDragDropFiles = self.dll.SilentDragDropFiles
            self.SilentDragDropFiles.argtypes = [ctypes.POINTER(ctypes.c_wchar_p), ctypes.c_uint, ctypes.c_int, ctypes.c_int]
            self.SilentDragDropFiles.restype = ctypes.c_bool
            
            # 定义鼠标点击函数原型
            # BOOL SilentMouseClick(INT x, INT y, int clickType)
            self.SilentMouseClick = self.dll.SilentMouseClick
            self.SilentMouseClick.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
            self.SilentMouseClick.restype = ctypes.c_bool
            
            print("DLL加载成功")
            return True
        except Exception as e:
            error_msg = f"DLL加载失败: {str(e)}"
            print(error_msg)
            
            # 检查是否是依赖项缺失
            if "找不到模块" in str(e) or "无法找到模块" in str(e) or "Could not find module" in str(e):
                additional_info = "\n\n可能的解决方案:\n"
                
                # 检查MinGW运行时库
                additional_info += "1. 安装MinGW运行时库（libgcc_s_seh-1.dll、libstdc++-6.dll、libwinpthread-1.dll）\n"
                additional_info += "   - 这些文件通常位于MinGW的bin目录中（如Qt安装目录下的mingw64\\bin）\n"
                additional_info += "   - 最快解决方法：复制这些DLL文件到与libSilentDragDrop.dll相同的目录\n"
                
                # 提供获取MinGW DLL的具体步骤
                additional_info += "\n获取MinGW DLL的具体步骤：\n"
                additional_info += "a. 打开Qt Creator安装目录\n"
                additional_info += "b. 进入Tools\\mingw1120_64\\bin目录（或类似的MinGW bin目录）\n"
                additional_info += "c. 找到并复制以下文件到您的项目目录：\n"
                additional_info += "   - libgcc_s_seh-1.dll\n"
                additional_info += "   - libstdc++-6.dll\n"
                additional_info += "   - libwinpthread-1.dll\n"
                
                # 检查Visual C++ Redistributable
                additional_info += "\n2. 安装Visual C++ Redistributable（如果应用程序需要）\n"
                
                # 提供DLL依赖项检查工具建议
                additional_info += "3. 使用Dependencies Walker工具检查缺失的依赖项\n"
                additional_info += "   - 下载地址: https://www.dependencywalker.com/\n"
                additional_info += "   - 使用方法：启动工具后，打开libSilentDragDrop.dll查看缺失的依赖\n"
                
                # 检查Python和DLL位数是否匹配
                is_64bit_python = sys.maxsize > 2**32
                additional_info += f"\nPython版本: {is_64bit_python and '64位' or '32位'}\n"
                additional_info += "请确保Python和DLL位数匹配（同为32位或同为64位）\n"
                
                error_msg += additional_info
            
            self.dll = None
            self.SilentDragDropFiles = None
            return False
    
    def drag_drop_files(self, file_list, x, y):
        """执行拖放操作
        
        调用DLL中的SilentDragDropFiles函数，静默地将文件拖放到指定坐标位置。
        注意：当前版本的DLL已更新为不实际移动鼠标位置，而是静默地向系统发送拖放消息。
        坐标参数(x,y)用于指定拖放的目标位置，但不会影响鼠标的实际位置。
        
        参数:
            file_list: 要拖放的文件路径列表
            x: 目标位置的X坐标
            y: 目标位置的Y坐标
            
        返回:
            bool: 拖放操作成功返回True，否则返回False
        """
        if self.dll is None or self.SilentDragDropFiles is None:
            print("DLL未加载，无法执行拖放操作")
            # 尝试重新加载DLL
            if not self.load_dll():
                return False
        
        try:
            # 转换文件列表为C风格的宽字符串数组
            c_file_list = (ctypes.c_wchar_p * len(file_list))()
            for i, file_path in enumerate(file_list):
                c_file_list[i] = file_path
            
            # 提示用户DLL行为已更改
            print("注意：静默拖放操作将不实际移动您的鼠标位置")
            
            # 调用DLL函数
            result = self.SilentDragDropFiles(c_file_list, len(file_list), x, y)
            
            if result:
                # 检查日志文件以获取更详细的结果信息
                print(f"拖放操作执行完成: {file_list} 到坐标 ({x}, {y}) (静默模式，不实际移动鼠标)")
                print("注意：DLL返回成功，但请查看silentdragdrop_debug.log以确认实际拖放是否成功完成")
                print("如果日志中显示'Effect: 0'，则表示目标应用程序可能未接受拖放操作")
            else:
                print(f"拖放操作失败: {file_list} 到坐标 ({x}, {y})")
            
            return result
        except Exception as e:
            print(f"执行拖放操作时发生错误: {str(e)}")
            return False
    
    def mouse_click(self, x, y, click_type=0):
        """执行鼠标点击操作
        
        调用DLL中的SilentMouseClick函数，静默地执行鼠标点击操作。
        
        参数:
            x: 点击位置的X坐标
            y: 点击位置的Y坐标
            click_type: 点击类型（0=左键单击，1=右键单击，2=中键单击，3=左键双击，4=右键双击，5=中键双击）
            
        返回:
            bool: 点击操作成功返回True，否则返回False
        """
        if self.dll is None or self.SilentMouseClick is None:
            print("DLL未加载或SilentMouseClick函数未找到，无法执行鼠标点击操作")
            # 尝试重新加载DLL
            if not self.load_dll():
                return False
        
        try:
            # 调用DLL函数
            result = self.SilentMouseClick(x, y, click_type)
            
            click_type_str = {
                0: "左键单击",
                1: "右键单击",
                2: "中键单击",
                3: "左键双击",
                4: "右键双击",
                5: "中键双击"
            }.get(click_type, f"未知类型({click_type})")
            
            if result:
                print(f"鼠标点击操作执行完成: {click_type_str} 到坐标 ({x}, {y}) (静默模式，不实际移动鼠标)")
                print("注意：DLL返回成功，但请查看silentmouseoperation_debug.log以确认实际点击是否成功完成")
            else:
                print(f"鼠标点击操作失败: {click_type_str} 到坐标 ({x}, {y})")
            
            return result
        except Exception as e:
            print(f"执行鼠标点击操作时发生错误: {str(e)}")
            return False

class DragDropApp:
    """静默拖放工具图形用户界面类
    
    该类负责创建和管理用户界面，处理用户输入，并与DragDropSimulator类交互
    以执行静默拖放操作。
    
    属性:
        root: Tkinter主窗口对象
        drag_simulator: DragDropSimulator实例
        debug_mode: 调试模式开关
        file_listbox: 文件列表框控件
        x_entry: X坐标输入框
        y_entry: Y坐标输入框
    """
    def __init__(self, root):
        """初始化拖放应用程序
        
        参数:
            root: Tkinter主窗口对象
        """
        self.root = root
        self.root.title("静默鼠标操作工具")
        self.root.geometry("600x450")
        
        # 创建拖放模拟器实例
        self.drag_simulator = None
        self.debug_mode = False  # 调试模式开关
        self.initialize_dll()
        
        # 创建UI
        self.create_ui()
    
    def initialize_dll(self):
        """初始化DLL，尝试多个可能的路径
        
        该方法尝试从多个可能的位置加载DLL文件，以增强程序的兼容性和用户体验。
        首先尝试从当前目录加载，如果失败则尝试在常见的构建目录中查找。
        """
        # 尝试直接从当前目录加载
        self.drag_simulator = DragDropSimulator()
        
        # 如果加载失败，尝试在build目录中查找
        if self.drag_simulator.dll is None:
            possible_paths = [
                os.path.abspath(os.path.join("build", "Desktop_Qt_6_9_3_MinGW_64_bit-Debug", "libSilentDragDrop.dll"))
            ]
            
            for path in possible_paths:
                if os.path.exists(path):
                    self.drag_simulator = DragDropSimulator(path)
                    if self.drag_simulator.dll is not None:
                        break
        
        # 如果仍然加载失败，允许用户手动选择DLL
        if self.drag_simulator.dll is None:
            self.show_dependency_help()
            self.prompt_for_dll_path()
    
    def show_dependency_help(self):
        """显示依赖项帮助信息
        
        当DLL加载失败时，显示详细的依赖项帮助信息，指导用户如何解决常见的
        MinGW运行时库缺失问题。提供具体的步骤和文件列表，帮助用户快速解决问题。
        """
        help_msg = "DLL加载失败 - 依赖项问题\n\n"
        help_msg += "这通常是由于缺少MinGW运行时库导致的。\n\n"
        help_msg += "快速解决方案：\n"
        help_msg += "1. 找到Qt Creator安装目录下的MinGW bin文件夹\n"
        help_msg += "   （通常位于：C:\\Qt\\Tools\\mingw1120_64\\bin 或类似路径）\n"
        help_msg += "2. 复制以下文件到您的项目目录：\n"
        help_msg += "   - libgcc_s_seh-1.dll\n"
        help_msg += "   - libstdc++-6.dll\n"
        help_msg += "   - libwinpthread-1.dll\n"
        help_msg += "\n复制后重新启动程序。"
        
        messagebox.showinfo("依赖项帮助", help_msg)
    
    def prompt_for_dll_path(self):
        """提示用户手动选择DLL文件
        
        当自动加载DLL失败时，提示用户手动选择DLL文件的位置。这提供了一种备用
        机制，允许用户指定自定义路径下的DLL文件。如果用户选择的DLL仍然无法加载，
        则显示详细的错误信息。
        """
        messagebox.showwarning("DLL加载失败", "无法自动找到或加载libSilentMouseOperation.dll\n请手动选择DLL文件的位置。")
        
        dll_path = filedialog.askopenfilename(
            title="选择libSilentMouseOperation.dll文件",
            filetypes=[("DLL文件", "*.dll"), ("所有文件", "*")]
        )
        
        if dll_path:
            self.drag_simulator = DragDropSimulator(dll_path)
            if self.drag_simulator.dll is None:
                messagebox.showerror("DLL加载失败", "无法加载所选的DLL文件。\n请检查依赖项是否正确安装。\n\n详细解决方案已显示在终端输出中。")
        else:
            # 用户取消选择，显示错误信息但不退出程序
            messagebox.showinfo("DLL未加载", "DLL文件未加载，程序功能将受限。\n您可以稍后在菜单中重新加载DLL。")
    
    def create_ui(self):
        """创建用户界面
        
        该方法负责创建应用程序的所有用户界面组件，包括文件列表区域、
        目标位置输入区域和各种功能按钮。界面布局采用Frame容器和网格系统，
        确保在不同尺寸的窗口中都能良好显示。
        """
        # 添加自定义样式
        style = ttk.Style()
        style.configure("Accent.TButton", foreground="black", background="#4CAF50")
        
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建Tab控件
        tab_control = ttk.Notebook(main_frame)
        tab_control.pack(fill=tk.BOTH, expand=True)
        
        # 创建拖放Tab
        drag_drop_tab = ttk.Frame(tab_control)
        tab_control.add(drag_drop_tab, text="文件拖放")
        self.create_drag_drop_ui(drag_drop_tab)
        
        # 创建鼠标点击Tab
        mouse_click_tab = ttk.Frame(tab_control)
        tab_control.add(mouse_click_tab, text="鼠标点击")
        self.create_mouse_click_ui(mouse_click_tab)
        
        # 创建公共按钮区域
        common_buttons_frame = ttk.Frame(main_frame)
        common_buttons_frame.pack(fill=tk.X, pady=(10, 0))
        
        # 重新加载DLL按钮
        reload_dll_button = ttk.Button(common_buttons_frame, text="重新加载DLL", command=self.prompt_for_dll_path)
        reload_dll_button.pack(side=tk.LEFT, padx=5)
        
        # 依赖项帮助按钮
        help_button = ttk.Button(common_buttons_frame, text="依赖项帮助", command=self.show_dependency_help)
        help_button.pack(side=tk.LEFT, padx=5)
        
        # 调试模式复选框
        self.debug_var = tk.BooleanVar(value=False)
        debug_checkbox = ttk.Checkbutton(common_buttons_frame, text="调试模式", variable=self.debug_var, command=self.toggle_debug_mode)
        debug_checkbox.pack(side=tk.LEFT, padx=5)
    
    def toggle_debug_mode(self):
        """切换调试模式"""
        self.debug_mode = self.debug_var.get()
        print(f"调试模式已{'开启' if self.debug_mode else '关闭'}")
    
    def create_drag_drop_ui(self, parent):
        """创建文件拖放界面"""
        # 文件列表区域
        files_frame = ttk.LabelFrame(parent, text="文件列表", padding="10")
        files_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 创建滚动条和列表框
        self.file_listbox = tk.Listbox(files_frame, selectmode=tk.EXTENDED, width=70, height=10)
        scrollbar = ttk.Scrollbar(files_frame, orient=tk.VERTICAL, command=self.file_listbox.yview)
        self.file_listbox.config(yscrollcommand=scrollbar.set)
        
        self.file_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 按钮区域
        buttons_frame = ttk.Frame(parent)
        buttons_frame.pack(fill=tk.X, pady=(0, 10))
        
        add_button = ttk.Button(buttons_frame, text="添加文件", command=self.add_files)
        add_button.pack(side=tk.LEFT, padx=5)
        
        remove_button = ttk.Button(buttons_frame, text="移除选中", command=self.remove_selected)
        remove_button.pack(side=tk.LEFT, padx=5)
        
        clear_button = ttk.Button(buttons_frame, text="清空列表", command=self.clear_list)
        clear_button.pack(side=tk.LEFT, padx=5)
        
        # 目标位置区域
        target_frame = ttk.LabelFrame(parent, text="目标位置", padding="10")
        target_frame.pack(fill=tk.X, pady=(0, 10))
        
        # X坐标
        x_frame = ttk.Frame(target_frame)
        x_frame.pack(fill=tk.X, pady=(0, 5))
        
        x_label = ttk.Label(x_frame, text="X坐标:", width=10)
        x_label.pack(side=tk.LEFT, padx=5)
        
        self.x_entry = ttk.Entry(x_frame, width=10)
        self.x_entry.insert(0, "0")
        self.x_entry.pack(side=tk.LEFT, padx=5)
        
        # Y坐标
        y_frame = ttk.Frame(target_frame)
        y_frame.pack(fill=tk.X)
        
        y_label = ttk.Label(y_frame, text="Y坐标:", width=10)
        y_label.pack(side=tk.LEFT, padx=5)
        
        self.y_entry = ttk.Entry(y_frame, width=10)
        self.y_entry.insert(0, "0")
        self.y_entry.pack(side=tk.LEFT, padx=5)
        
        # 设定拖放目标位置按钮
        get_pos_button = ttk.Button(y_frame, text="设定拖放目标位置", command=self.get_current_pos)
        get_pos_button.pack(side=tk.LEFT, padx=5)
        
        # 执行拖放按钮
        execute_frame = ttk.Frame(parent)
        execute_frame.pack(fill=tk.X)
        
        execute_button = ttk.Button(
            execute_frame, 
            text="执行拖放", 
            command=self.execute_drag_drop,
            style="Accent.TButton"
        )
        execute_button.pack(side=tk.RIGHT, padx=5)
    
    def create_mouse_click_ui(self, parent):
        """创建鼠标点击界面"""
        # 创建鼠标点击目标位置区域
        click_target_frame = ttk.LabelFrame(parent, text="点击位置", padding="10")
        click_target_frame.pack(fill=tk.X, pady=(0, 10))
        
        # X坐标
        click_x_frame = ttk.Frame(click_target_frame)
        click_x_frame.pack(fill=tk.X, pady=(0, 5))
        
        click_x_label = ttk.Label(click_x_frame, text="X坐标:", width=10)
        click_x_label.pack(side=tk.LEFT, padx=5)
        
        self.click_x_entry = ttk.Entry(click_x_frame, width=10)
        self.click_x_entry.insert(0, "0")
        self.click_x_entry.pack(side=tk.LEFT, padx=5)
        
        # Y坐标
        click_y_frame = ttk.Frame(click_target_frame)
        click_y_frame.pack(fill=tk.X)
        
        click_y_label = ttk.Label(click_y_frame, text="Y坐标:", width=10)
        click_y_label.pack(side=tk.LEFT, padx=5)
        
        self.click_y_entry = ttk.Entry(click_y_frame, width=10)
        self.click_y_entry.insert(0, "0")
        self.click_y_entry.pack(side=tk.LEFT, padx=5)
        
        # 设定点击目标位置按钮
        set_click_pos_button = ttk.Button(click_y_frame, text="设定点击位置", command=self.get_click_pos)
        set_click_pos_button.pack(side=tk.LEFT, padx=5)
        
        # 点击类型选择区域
        click_type_frame = ttk.LabelFrame(parent, text="点击类型", padding="10")
        click_type_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 点击类型变量
        self.click_type_var = tk.IntVar(value=0)
        
        # 单击选项
        click_type_frame1 = ttk.Frame(click_type_frame)
        click_type_frame1.pack(fill=tk.X, pady=(0, 5))
        
        ttk.Radiobutton(click_type_frame1, text="左键单击", variable=self.click_type_var, value=0).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(click_type_frame1, text="右键单击", variable=self.click_type_var, value=1).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(click_type_frame1, text="中键单击", variable=self.click_type_var, value=2).pack(side=tk.LEFT, padx=5)
        
        # 双击选项
        click_type_frame2 = ttk.Frame(click_type_frame)
        click_type_frame2.pack(fill=tk.X)
        
        ttk.Radiobutton(click_type_frame2, text="左键双击", variable=self.click_type_var, value=3).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(click_type_frame2, text="右键双击", variable=self.click_type_var, value=4).pack(side=tk.LEFT, padx=5)
        ttk.Radiobutton(click_type_frame2, text="中键双击", variable=self.click_type_var, value=5).pack(side=tk.LEFT, padx=5)
        
        # 执行点击按钮
        click_execute_frame = ttk.Frame(parent)
        click_execute_frame.pack(fill=tk.X)
        
        execute_click_button = ttk.Button(
            click_execute_frame, 
            text="执行点击", 
            command=self.execute_mouse_click,
            style="Accent.TButton"
        )
        execute_click_button.pack(side=tk.RIGHT, padx=5)
    
    def add_files(self):
        """添加文件到拖放列表
        
        打开文件选择对话框，允许用户选择一个或多个文件添加到拖放列表中。
        选择的文件将直接添加到列表框中。
        """
        files = filedialog.askopenfilenames(title="选择要拖放的文件")
        for file in files:
            self.file_listbox.insert(tk.END, file)
    
    def remove_selected(self):
        """移除列表中选中的文件
        
        从文件列表中移除用户当前选中的文件项。由于列表索引会随删除操作变化，
        采用从后往前删除的策略，确保所有选中项都能被正确移除。
        """
        selected_indices = sorted(self.file_listbox.curselection(), reverse=True)
        for index in selected_indices:
            self.file_listbox.delete(index)
    
    def clear_list(self):
        """清空所有文件列表
        
        删除文件列表中的所有文件项，重置列表为空状态，为新的拖放操作做准备。
        """
        self.file_listbox.delete(0, tk.END)
    
    def get_current_pos(self):
        """获取当前鼠标位置（带实时倒计时）- 用于拖放"""
        try:
            # 创建倒计时窗口
            countdown_window = tk.Toplevel(self.root)
            countdown_window.title("倒计时")
            countdown_window.geometry("300x200")
            countdown_window.resizable(False, False)
            countdown_window.transient(self.root)  # 设置为模态窗口
            countdown_window.grab_set()  # 捕获所有输入
            
            # 居中显示
            countdown_window.update_idletasks()
            x = (countdown_window.winfo_screenwidth() - countdown_window.winfo_width()) // 2
            y = (countdown_window.winfo_screenheight() - countdown_window.winfo_height()) // 2
            countdown_window.geometry(f"+{x}+{y}")
            
            # 创建倒计时标签
            countdown_label = ttk.Label(countdown_window, text="请将鼠标移动到拖放目标位置", font=("Arial", 12))
            countdown_label.pack(pady=20)
            
            # 创建倒计时显示
            time_label = ttk.Label(countdown_window, text="3", font=("Arial", 24, "bold"))
            time_label.pack(pady=10)
            
            # 创建提示标签
            hint_label = ttk.Label(countdown_window, text="倒计时结束后将记录当前鼠标位置", font=("Arial", 10))
            hint_label.pack(pady=5)
            
            # 初始化目标位置变量
            target_x = 0
            target_y = 0
            
            def update_countdown(seconds_left):
                if seconds_left > 0:
                    time_label.config(text=str(seconds_left))
                    
                    # 在倒计时期间持续获取鼠标位置
                    class POINT(ctypes.Structure):
                        _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
                    
                    point = POINT()
                    ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
                    
                    # 更新目标位置为当前鼠标位置
                    nonlocal target_x, target_y
                    target_x = point.x
                    target_y = point.y
                    
                    # 1秒后继续倒计时
                    countdown_window.after(1000, update_countdown, seconds_left - 1)
                else:
                    # 倒计时结束，锁定最终位置
                    time_label.config(text="0")
                    countdown_label.config(text="位置已记录！")
                    
                    # 短暂延迟后关闭窗口并设置坐标
                    countdown_window.after(500, lambda: finish_countdown(target_x, target_y))
            
            def finish_countdown(final_x, final_y):
                # 倒计时结束后，再次获取鼠标的最终位置
                class POINT(ctypes.Structure):
                    _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
                
                point = POINT()
                ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
                
                # 使用倒计时结束后的最终鼠标位置
                final_x = point.x
                final_y = point.y
                
                # 设置坐标到输入框
                self.x_entry.delete(0, tk.END)
                self.x_entry.insert(0, str(final_x))
                
                self.y_entry.delete(0, tk.END)
                self.y_entry.insert(0, str(final_y))
                
                # 关闭倒计时窗口
                countdown_window.destroy()
                
                # 显示成功信息
                if self.debug_mode:
                    messagebox.showinfo("成功", f"拖放目标位置已设置为: ({final_x}, {final_y})\n\n这是倒计时结束后鼠标的最终位置。")
            
            # 开始倒计时
            update_countdown(3)
            
        except Exception as e:
            messagebox.showerror("错误", f"获取鼠标位置失败: {str(e)}")
    
    def get_click_pos(self):
        """获取当前鼠标位置（带实时倒计时）- 用于鼠标点击"""
        try:
            # 创建倒计时窗口
            countdown_window = tk.Toplevel(self.root)
            countdown_window.title("倒计时")
            countdown_window.geometry("300x200")
            countdown_window.resizable(False, False)
            countdown_window.transient(self.root)  # 设置为模态窗口
            countdown_window.grab_set()  # 捕获所有输入
            
            # 居中显示
            countdown_window.update_idletasks()
            x = (countdown_window.winfo_screenwidth() - countdown_window.winfo_width()) // 2
            y = (countdown_window.winfo_screenheight() - countdown_window.winfo_height()) // 2
            countdown_window.geometry(f"+{x}+{y}")
            
            # 创建倒计时标签
            countdown_label = ttk.Label(countdown_window, text="请将鼠标移动到点击目标位置", font=("Arial", 12))
            countdown_label.pack(pady=20)
            
            # 创建倒计时显示
            time_label = ttk.Label(countdown_window, text="3", font=("Arial", 24, "bold"))
            time_label.pack(pady=10)
            
            # 创建提示标签
            hint_label = ttk.Label(countdown_window, text="倒计时结束后将记录当前鼠标位置", font=("Arial", 10))
            hint_label.pack(pady=5)
            
            # 初始化目标位置变量
            target_x = 0
            target_y = 0
            
            def update_countdown(seconds_left):
                if seconds_left > 0:
                    time_label.config(text=str(seconds_left))
                    
                    # 在倒计时期间持续获取鼠标位置
                    class POINT(ctypes.Structure):
                        _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
                    
                    point = POINT()
                    ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
                    
                    # 更新目标位置为当前鼠标位置
                    nonlocal target_x, target_y
                    target_x = point.x
                    target_y = point.y
                    
                    # 1秒后继续倒计时
                    countdown_window.after(1000, update_countdown, seconds_left - 1)
                else:
                    # 倒计时结束，锁定最终位置
                    time_label.config(text="0")
                    countdown_label.config(text="位置已记录！")
                    
                    # 短暂延迟后关闭窗口并设置坐标
                    countdown_window.after(500, lambda: finish_countdown(target_x, target_y))
            
            def finish_countdown(final_x, final_y):
                # 倒计时结束后，再次获取鼠标的最终位置
                class POINT(ctypes.Structure):
                    _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
                
                point = POINT()
                ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
                
                # 使用倒计时结束后的最终鼠标位置
                final_x = point.x
                final_y = point.y
                
                # 设置坐标到输入框
                self.click_x_entry.delete(0, tk.END)
                self.click_x_entry.insert(0, str(final_x))
                
                self.click_y_entry.delete(0, tk.END)
                self.click_y_entry.insert(0, str(final_y))
                
                # 关闭倒计时窗口
                countdown_window.destroy()
                
                # 显示成功信息
                if self.debug_mode:
                    messagebox.showinfo("成功", f"点击目标位置已设置为: ({final_x}, {final_y})\n\n这是倒计时结束后鼠标的最终位置。")
            
            # 开始倒计时
            update_countdown(3)
            
        except Exception as e:
            messagebox.showerror("错误", f"获取鼠标位置失败: {str(e)}")
    
    def execute_drag_drop(self):
        """执行真正的静默拖放操作"""
        # 检查DLL是否加载
        if self.drag_simulator is None or self.drag_simulator.dll is None:
            messagebox.showerror("DLL未加载", "无法执行拖放操作，因为DLL文件未加载成功。\n请先加载libSilentMouseOperation.dll。")
            self.prompt_for_dll_path()
            return
        
        # 获取文件列表
        file_list = list(self.file_listbox.get(0, tk.END))
        if not file_list:
            messagebox.showwarning("警告", "请先添加要拖放的文件。")
            return
        
        # 获取坐标
        try:
            x = int(self.x_entry.get())
            y = int(self.y_entry.get())
        except ValueError:
            messagebox.showerror("错误", "请输入有效的坐标值。")
            return
        
        # 真正的静默拖放：不显示任何提示，不移动鼠标
        # 在后台线程中执行，避免干扰用户
        self.root.after(100, lambda: self.execute_silent_drag_drop(file_list, x, y))
    
    def execute_mouse_click(self):
        """执行鼠标点击操作"""
        # 检查DLL是否加载
        if self.drag_simulator is None or self.drag_simulator.dll is None:
            messagebox.showerror("DLL未加载", "无法执行鼠标点击操作，因为DLL文件未加载成功。\n请先加载libSilentMouseOperation.dll。")
            self.prompt_for_dll_path()
            return
        
        # 获取坐标
        try:
            x = int(self.click_x_entry.get())
            y = int(self.click_y_entry.get())
        except ValueError:
            messagebox.showerror("错误", "请输入有效的坐标值。")
            return
        
        # 获取点击类型
        click_type = self.click_type_var.get()
        
        # 在后台线程中执行，避免干扰用户
        self.root.after(100, lambda: self.execute_silent_mouse_click(x, y, click_type))
    
    def execute_silent_drag_drop(self, file_list, x, y):
        """执行真正的静默拖放操作"""
        try:
            # 静默执行拖放操作
            print(f"静默拖放: {file_list} -> ({x},{y})")
            result = self.drag_simulator.drag_drop_files(file_list, x, y)
            
            # 静默显示结果（可选）
            if result:
                print("拖放操作成功完成")
                # 可以选择不显示消息框，或者只在调试模式下显示
                if self.debug_mode:
                    messagebox.showinfo("成功", "拖放操作执行成功！")
            else:
                print("拖放操作失败")
                if self.debug_mode:
                    messagebox.showerror("失败", "拖放操作失败。\n可能的原因：\n1. 目标应用程序不接受拖放\n2. 坐标无效\n3. 文件路径无效")
                
        except Exception as e:
            print(f"执行拖放操作时发生错误: {str(e)}")
            if self.debug_mode:
                messagebox.showerror("错误", f"执行拖放操作时发生错误: {str(e)}")
    
    def execute_silent_mouse_click(self, x, y, click_type):
        """在后台线程中执行鼠标点击操作"""
        try:
            # 静默执行点击操作
            click_type_str = {
                0: "左键单击",
                1: "右键单击",
                2: "中键单击",
                3: "左键双击",
                4: "右键双击",
                5: "中键双击"
            }.get(click_type, f"未知类型({click_type})")
            
            print(f"静默点击: {click_type_str} -> ({x},{y})")
            result = self.drag_simulator.mouse_click(x, y, click_type)
            
            # 静默显示结果（可选）
            if result:
                print("鼠标点击操作成功完成")
                # 可以选择不显示消息框，或者只在调试模式下显示
                if self.debug_mode:
                    messagebox.showinfo("成功", f"鼠标点击操作执行成功！\n类型: {click_type_str}\n位置: ({x}, {y})")
            else:
                print("鼠标点击操作失败")
                if self.debug_mode:
                    messagebox.showerror("失败", "鼠标点击操作失败。\n可能的原因：\n1. 坐标无效\n2. DLL调用失败")
                
        except Exception as e:
            print(f"执行鼠标点击操作时发生错误: {str(e)}")
            if self.debug_mode:
                messagebox.showerror("错误", f"执行鼠标点击操作时发生错误: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = DragDropApp(root)
    root.mainloop()